package com.example.loginpilot_01.service.notice.impl;

import com.example.loginpilot_01.entity.Announcement;
import com.example.loginpilot_01.mapper.NoticeMapper;
import com.example.loginpilot_01.mapper.NoticeReadLogMapper;
import com.example.loginpilot_01.pojo.dto.NoticeQueryDTO;
import com.example.loginpilot_01.pojo.dto.NoticeStatDTO;
import com.example.loginpilot_01.pojo.dto.PageResult;
import com.example.loginpilot_01.pojo.entity.NoticeReadLog;
import com.example.loginpilot_01.service.notice.NoticeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
//注解@Slf4j用于日志记录,是lombok提供的注解,用于自动注入日志记录器
@Slf4j
public class NoticeServiceImpl implements NoticeService {
    //@Autowired注解用于自动注入NoticeMapper和NoticeReadLogMapper
    @Autowired
    private NoticeMapper noticeMapper;

    @Autowired
    private NoticeReadLogMapper readLogMapper;

    @Override
    public PageResult<Announcement> getAnnouncementList(NoticeQueryDTO query, Long currentUserId) {
        log.info("查询通知列表，参数: {}, 用户ID: {}", query, currentUserId);

        // 查询通知列表
        List<Announcement> announcements = noticeMapper.selectAnnouncementList(query);
        Long total = noticeMapper.countAnnouncementList(query);

        // 获取用户阅读状态和阅读统计
        if (currentUserId != null && !announcements.isEmpty()) {
            setUserReadStatus(announcements, currentUserId);
            setReadCount(announcements);
        }

        return new PageResult<>(announcements, total, query.getPageNum(), query.getPageSize());
    }

    @Override
    @Transactional
    public Announcement getAnnouncementDetail(Long announcementId, Long currentUserId) {
        log.info("查询通知详情，通知ID: {}, 用户ID: {}", announcementId, currentUserId);

        // 查询通知详情
        Announcement announcement = noticeMapper.selectAnnouncementById(announcementId);
        if (announcement == null) {
            throw new RuntimeException("通知不存在");
        }

        // 记录阅读行为
        if (currentUserId != null) {
            recordReadBehavior(announcementId, currentUserId);
        }

        // 设置阅读人数
        setReadCount(Collections.singletonList(announcement));

        return announcement;
    }

    @Override
    public NoticeStatDTO getAnnouncementStatistics(Long announcementId) {
        log.info("获取通知统计，通知ID: {}", announcementId);

        List<NoticeStatDTO> stats = noticeMapper.selectNoticeStats(Collections.singletonList(announcementId));
        return stats.stream().findFirst().orElse(new NoticeStatDTO(announcementId,0L,0L));
    }

    @Override
    public Map<Long, Long> getBatchReadStatistics(List<Long> announcementIds) {
        if (announcementIds.isEmpty()) {
            return new HashMap<>();
        }

        List<NoticeStatDTO> stats = noticeMapper.selectNoticeStats(announcementIds);
        //将查询结果转换为Map,键为通知ID,值为总阅读人数
        return stats.stream().collect(Collectors.toMap(NoticeStatDTO::getAnnouncementId, NoticeStatDTO::getTotalReadCount));
    }

    //设置用户阅读状态
    //用于查询通知列表时，展示每个通知是否已被当前用户阅读
    private void setUserReadStatus(List<Announcement> announcements, Long currentUserId) {
        List<Long> announcementIds = announcements.stream()
                .map(announcement -> announcement.getId().longValue())
                .collect(Collectors.toList());
        List<NoticeReadLog> readLogs = readLogMapper.selectUserReadStatus(currentUserId, announcementIds);

        Map<Long, NoticeReadLog> readMap = readLogs.stream()
                .collect(Collectors.toMap(NoticeReadLog::getAnnouncementId, Function.identity()));

        //将查询结果转换为Map,键为通知ID,值为阅读日志
        //这里用于遍历通知列表,设置每个通知的阅读状态
        //readMap.containsKey(notice.getId())判断当前通知是否已被当前用户阅读
        //如果已被阅读,则设置readStatus为true,否则为false
        announcements.forEach(announcement ->
                announcement.setReadStatus(readMap.containsKey(announcement.getId()))
        );
    }

    //设置阅读人数
    //用于查询通知列表时，展示每个通知的总阅读人数
    private void setReadCount(List<Announcement> announcements) {
        if (announcements.isEmpty()) return;

        List<Long> announcementIds = announcements.stream()
                .map(announcement ->announcement.getId().longValue())
                .collect(Collectors.toList());
        Map<Long, Long> readCountMap = getBatchReadStatistics(announcementIds);

        //readCountMap.getOrDefault(notice.getId(), 0L)获取当前通知的总阅读人数,如果不存在,则默认值为0
        announcements.forEach(announcement ->
                announcement.setReadCount(readCountMap.getOrDefault(announcement.getId(), 0L))
        );
    }

    //记录阅读行为
    //用于查询通知详情时，记录当前用户对通知的阅读行为
    private void recordReadBehavior(Long announcementId, Long userId) {
        try {
            // 检查是否已读
            Integer readCount = noticeMapper.checkUserReadStatus(announcementId, userId);
            if (readCount == 0) {
                NoticeReadLog log = new NoticeReadLog();
                log.setAnnouncementId(announcementId);
                log.setUserId(userId);
                log.setReadTime(LocalDateTime.now());
                readLogMapper.insertReadLog(log);
                log.info("记录用户阅读行为，用户ID: {}, 通知ID: {}", userId, announcementId);
            }
        } catch (Exception e) {
            log.error("记录阅读行为失败: announcementId={}, userId={}", announcementId, userId, e);
            // 记录失败不影响主流程
        }
    }
}
